"""
配置管理模块
统一管理系统配置，所有配置参数都从YAML文件读取
"""

import os
import yaml
from pathlib import Path
from typing import Any, Dict, Optional

# 避免循环导入，使用简单的打印函数
def _log_info(message: str):
    """简单的日志函数，避免循环导入"""
    print(f"[CONFIG] {message}")

def _log_error(message: str):
    """简单的错误日志函数，避免循环导入"""
    print(f"[CONFIG ERROR] {message}")

def _log_warning(message: str):
    """简单的警告日志函数，避免循环导入"""
    print(f"[CONFIG WARNING] {message}")


class ConfigManager:
    """
    配置管理器类
    
    用途：
    - 加载和管理YAML配置文件
    - 提供配置参数的统一访问接口
    - 支持配置文件的热重载
    
    特点：
    - 所有配置参数都从配置文件读取
    - 不在代码中提供默认值
    - 配置文件不存在时会抛出异常
    """
    
    def __init__(self, config_file: str = "config.yaml"):
        """
        初始化配置管理器
        
        参数：
            config_file (str): 配置文件路径
        """
        self.config_file = Path(config_file)
        self.config_data = {}
        self.load_config()
    
    def load_config(self):
        """
        加载配置文件
        
        异常：
            FileNotFoundError: 配置文件不存在
            yaml.YAMLError: YAML格式错误
        """
        if not self.config_file.exists():
            raise FileNotFoundError(f"配置文件不存在: {self.config_file}")
        
        try:
            with open(self.config_file, 'r', encoding='utf-8') as f:
                self.config_data = yaml.safe_load(f) or {}
            
            _log_info(f"配置文件加载成功: {self.config_file}")
            
        except yaml.YAMLError as e:
            _log_error(f"配置文件格式错误: {e}")
            raise
        except Exception as e:
            _log_error(f"加载配置文件失败: {e}")
            raise
    
    def reload_config(self):
        """
        重新加载配置文件
        """
        _log_info("重新加载配置文件")
        self.load_config()
    
    def get(self, key: str, default: Any = None) -> Any:
        """
        获取配置值
        
        参数：
            key (str): 配置键，支持点号分隔的嵌套键（如 'model.yolo_model'）
            default (Any): 默认值（仅在开发阶段使用，生产环境应移除）
            
        返回值：
            Any: 配置值
            
        异常：
            KeyError: 配置键不存在且未提供默认值
        """
        keys = key.split('.')
        value = self.config_data
        
        try:
            for k in keys:
                value = value[k]
            return value
        except (KeyError, TypeError):
            if default is not None:
                _log_warning(f"配置键 '{key}' 不存在，使用默认值: {default}")
                return default
            else:
                raise KeyError(f"配置键 '{key}' 不存在，且未提供默认值")
    
    def set(self, key: str, value: Any):
        """
        设置配置值（运行时修改，不保存到文件）
        
        参数：
            key (str): 配置键
            value (Any): 配置值
        """
        keys = key.split('.')
        config_dict = self.config_data
        
        # 创建嵌套字典结构
        for k in keys[:-1]:
            if k not in config_dict:
                config_dict[k] = {}
            config_dict = config_dict[k]
        
        config_dict[keys[-1]] = value
        # 配置更新不需要日志，避免过多输出
    
    def get_section(self, section: str) -> Dict:
        """
        获取配置段落
        
        参数：
            section (str): 段落名称
            
        返回值：
            Dict: 配置段落字典
            
        异常：
            KeyError: 段落不存在
        """
        if section not in self.config_data:
            raise KeyError(f"配置段落 '{section}' 不存在")
        
        return self.config_data[section]
    
    def has_key(self, key: str) -> bool:
        """
        检查配置键是否存在
        
        参数：
            key (str): 配置键
            
        返回值：
            bool: 是否存在
        """
        try:
            self.get(key)
            return True
        except KeyError:
            return False
    
    def get_all_config(self) -> Dict:
        """
        获取所有配置
        
        返回值：
            Dict: 完整配置字典
        """
        return self.config_data.copy()
    
    def validate_config(self) -> bool:
        """
        验证配置文件的完整性
        
        返回值：
            bool: 配置是否有效
        """
        required_sections = [
            'model',
            'image_processing', 
            'paths',
            'gui',
            'logging',
            'recognition',
            'app_info',
            'file_formats',
            'performance'
        ]
        
        missing_sections = []
        for section in required_sections:
            if section not in self.config_data:
                missing_sections.append(section)
        
        if missing_sections:
            _log_error(f"配置文件缺少必需的段落: {missing_sections}")
            return False
        
        # 检查关键配置项
        required_keys = [
            'model.yolo_model',
            'model.ocr_languages',
            'paths.output_dir',
            'app_info.name',
            'gui.window_size'
        ]
        
        missing_keys = []
        for key in required_keys:
            if not self.has_key(key):
                missing_keys.append(key)
        
        if missing_keys:
            _log_error(f"配置文件缺少必需的配置项: {missing_keys}")
            return False
        
        _log_info("配置文件验证通过")
        return True
    
    def save_config(self, output_file: Optional[str] = None):
        """
        保存配置到文件
        
        参数：
            output_file (str): 输出文件路径，默认为原配置文件
        """
        output_path = Path(output_file) if output_file else self.config_file
        
        try:
            with open(output_path, 'w', encoding='utf-8') as f:
                yaml.dump(self.config_data, f, 
                         default_flow_style=False, 
                         allow_unicode=True, 
                         indent=2)
            
            _log_info(f"配置已保存到: {output_path}")
            
        except Exception as e:
            _log_error(f"保存配置文件失败: {e}")
            raise


# 为了保持向后兼容，创建Config类的别名
Config = ConfigManager

# 创建全局配置实例
config = ConfigManager()

# 导出的公共接口
__all__ = ['ConfigManager', 'Config', 'config']

# 启动时验证配置
if not config.validate_config():
    raise RuntimeError("配置文件验证失败，请检查config.yaml文件") 